#include <QTextBlock>
#include <QPainter>
#include "TextEditorMargine.h"
#include "TextEditor.h"

TextEditorMargine::TextEditorMargine(TextEditor *editor) :
    QWidget(editor),
    _editor(editor)
{
    connect(_editor, SIGNAL(blockCountChanged(int)), this, SLOT(updateLineNumberAreaWidth(int)));
    connect(_editor, SIGNAL(updateRequest(QRect,int)), this, SLOT(updateLineNumberArea(QRect,int)));

    updateLineNumberAreaWidth(0);
}

QSize TextEditorMargine::sizeHint() const {
    return QSize(lineNumberAreaWidth(), 0);
}

void TextEditorMargine::paintEvent(QPaintEvent *event) {
    QPainter painter(this);
    painter.fillRect(event->rect(), Qt::lightGray);

    QTextBlock block = _editor->firstVisibleBlock();
    int blockNumber = block.blockNumber();
    int top = (int) _editor->blockBoundingGeometry(block).translated(_editor->contentOffset()).top();
    int bottom = top + (int) _editor->blockBoundingRect(block).height();

    while (block.isValid() && top <= event->rect().bottom()) {
        if (block.isVisible() && bottom >= event->rect().top()) {
            QString number = QString::number(blockNumber + 1);
            painter.setPen(Qt::black);
            painter.drawText(0, top, width(), fontMetrics().height(), Qt::AlignRight, number);
        }

        block = block.next();
        top = bottom;
        bottom = top + (int) _editor->blockBoundingRect(block).height();
        ++blockNumber;
    }
}

int TextEditorMargine::lineNumberAreaWidth() const
{
    int digits = 1;
    int max = qMax(1, _editor->blockCount());
    while (max >= 10) {
        max /= 10;
        ++digits;
    }

    int space = 3 + fontMetrics().width(QLatin1Char('9')) * digits;

    return space;
}

void TextEditorMargine::updateLineNumberAreaWidth(int /* newBlockCount */)
{
    _editor->setViewportMargins(lineNumberAreaWidth(), 0, 0, 0);
}

void TextEditorMargine::updateLineNumberArea(const QRect &rect, int dy)
{
    if (dy)
        scroll(0, dy);
    else
        update(0, rect.y(), width(), rect.height());

    if (rect.contains(_editor->viewport()->rect()))
        updateLineNumberAreaWidth(0);
}

